package org.mtmi.ui.controls.popups;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.mtmi.ui.GraphicUtil;
import org.mtmi.ui.M;
import org.mtmi.ui.controls.Button;
import org.mtmi.ui.controls.Control;
import org.mtmi.ui.controls.listeners.TapAdapter;
import org.mtmi.ui.controls.listeners.TapEvent;
import org.mtmi.ui.controls.listeners.PopupListener;
import org.mtmi.ui.layouts.GridData;
import org.mtmi.ui.layouts.GridLayout;
import org.mtmi.ui.layouts.LayoutData;
import org.mtmi.ui.scenes.COLOR;
import org.mtmi.ui.scenes.FontManager;
import org.mtmi.ui.scenes.Scene;

/**
 * provide framework for a popup with a title and button bar.
 * The contents can be freely designed.
 */
public abstract class AbstractButtonPopup extends Popup
{
	/** id for OK button, a button that close the popup */
	public static final int OK = 0;
	/** id for CANCEL button, a button that close the popup */
	public static final int CANCEL = 1;
	
	private static final int MG=20; //margin
	
	private List<Button> buttons;
	private TapAdapter button_tap_listener;
	
	private List<PopupListener> listeners;
	private Rectangle r_contents, r_popup;
	
	private String title;
	
	public AbstractButtonPopup( Scene scene, String _title, int flags ) {
		super(scene, flags);
		setBackground( COLOR.grey50 );
		setForeground( COLOR.grey100 );
		title = _title;
		buttons = new ArrayList<Button>();
		button_tap_listener = new TapAdapter() {
			@Override
			public void controlTappedDown(TapEvent event) {
				int id = ((Button)event.control).getData( D_BUTTON_ID, -1 );
				buttonTapped( id );
			}
		};
		
		//popup have scene size to avoid other control to get events
		Point ss = scene.getSize();
		setSize( ss );
		setLocation( 0, 0 );
		
		r_contents = createContents( scene );
		
		createButtons();
		
		int r = r_contents.x+r_contents.width;//right
		int yb = r_contents.y+r_contents.height+MG; 
		GridLayout gl = new GridLayout( buttons.size(), true );
		gl.setSpacings( MG );
		Control c [] = buttons.toArray( new Control[buttons.size()] );
		GC gc = new GC( getScene() );
		try {
			Point st ;
			if( title!=null ) {
				gc.setFont( FontManager.getInstance().getTitleFont() );
				st = gc.textExtent( title );
			} else {
				st = new Point(0,0);
			}
			
			LayoutData ld = new LayoutData( gc, r_contents.x, yb, r_contents.width,0 );
			Point s = gl.computeSize( ld, c );
			if( s.x > r_contents.width ) { //h center button
				ld.lx = r_contents.x+(r_contents.width-s.x)/2;
 			} else { //button on the right of contents
				ld.lx = r - s.x;
			}
			ld.lw = s.x;
			gl.layout( ld, c );
			
			int xt = r_contents.x;
			if( st.x > r_contents.width ) { //title also h centered
				xt = r_contents.x+(r_contents.width-st.x)/2;
			}
			int l = Math.min( Math.min( r_contents.x, ld.lx ), xt );
			int w = Math.max( r_contents.width, Math.max( ld.lw, st.x ) );
			int y = r_contents.y-MG;
			if( title!=null ) {
				y -= st.y+MG;
			}
			int btmy = yb + buttons.get(0).getSize().y+MG;
			r_popup = new Rectangle( l-MG, y, w+2*MG, btmy-y );
		} finally {
			gc.dispose();
		}
		
	}
	
	/** create popup content controls and return their bounds to place popup decoration */
	public abstract Rectangle createContents( Scene _scene );

	private static final String D_BUTTON_ID = "idBtn@ButtonPopup"; //$NON-NLS-1$
	
	/** @return the button created with given id, or null */
	protected Button getButton( int id ) {
		for( Button b : buttons ) {
			if( b.getData( D_BUTTON_ID, -1 )==id ) return b;
		}
		return null;
	}
	
	protected Button addButton( String text, int id ) {
		Button btn = new Button( getScene(), text, flags & M.SCENE_EDITOR_CONTROL );
		btn.setData( D_BUTTON_ID, id );
		btn.setData( M.D_LAYOUT_DATA, new GridData( M.FILL,false,M.FILL,false) );
		btn.addTapListener( button_tap_listener );
		buttons.add( btn );
		return btn;
	}
	
	/** 
	 * Create button for button bar, default are Ok, Cancel.
	 * Override to redefine, use addButton().
	 */
	protected void createButtons() {
		addButton( "Ok", OK );
		addButton( "Cancel", CANCEL );
	}
	
	protected void buttonTapped( int id ) {
		if( id==OK || id==CANCEL ) {
			terminate( id );
		}
	}
		
	private void notifyPopupListener( int id ) {
		if( listeners!=null ) {
			for (PopupListener l : listeners) {
				l.popupButtonSelected( id );
			}
		}
	}
	
	protected void terminate( int id ) {
		notifyPopupListener( id );
		dispose();
		for( Button b: buttons ) b.dispose();
		buttons.clear();
		buttons=null;
		redraw();
	}
	
	public void addResponseListener(PopupListener listener) {
		if( listeners==null ) {
			listeners = new ArrayList<PopupListener>();
		}
		if(!listeners.contains(listener)) {
			listeners.add(listener);
		}
	}

	public void removeResponseListener(PopupListener listener) {
		listeners.remove(listener);
	}
	
	@Override 
	public void paintContent( GC gc, int width, int height )
	{
		Path p = GraphicUtil.getRoundRectangle( gc, r_popup.x, r_popup.y, r_popup.width, r_popup.height, 25, 25 );
		
		gc.setBackground( getBackground() );
		gc.fillPath( p );
		gc.setForeground( getForeground() );
		gc.setLineWidth( 5 );
		gc.drawPath( p );
		p.dispose();

		gc.setLineWidth( 0 );
		
		if( title!=null ) {
			Font f = gc.getFont();
			gc.setFont( FontManager.getInstance().getTitleFont() );
			gc.drawString( title, r_popup.x+MG, r_popup.y+MG, true );
			gc.setFont( f );
		}
		//other control are draw by scene.
	}

}
